using CfgTable;
using IQIGame.Onigao.GamePlay;
using System.Collections.Generic;

namespace IQIGame.Onigao.Logic
{
    /// <summary>
    /// 掉落模块
    /// </summary>
    public class LogicDropModule
    {
        public static LogicDropModule Instance { get; } = new LogicDropModule();

        /// <summary>
        /// 计算掉落
        /// </summary>
        /// <param name="player"></param>
        /// <param name="dropID"></param>
        /// <param name="num"></param>
        /// <returns></returns>
        public List<RawItemData> Drop(LevelPlayer player, int dropID, int num = 1)
        {
            if (num > 1000)
            {
                LogicLog.LogError($"drop cnt is too much , cnt = {num}, dropID = {dropID}");
                return new List<RawItemData>();
            }
            if (dropID <= 0)
            {
                return new List<RawItemData>();
            }
            List<int> dropIDList = new List<int>();
            dropIDList.Add(dropID);

            //处理掉落控制器
            CfgLevelDropLibControl cfgDropLibControl = GetDropLibControl(dropID);
            if (cfgDropLibControl != null)
            {
                for (int i = 0; i < cfgDropLibControl.ConditionId.Count; i++)
                {
                    if (ConditionLevelLogicUtil.Check(cfgDropLibControl.ConditionId[i], player.region, player).Item1)
                    {
                        if (cfgDropLibControl.ControlType[i] == 1)
                        {
                            dropIDList.Add(cfgDropLibControl.ExDropLibId[i]);
                        }
                        else if (cfgDropLibControl.ControlType[i] == 2)
                        {
                            dropIDList.Clear();
                            dropIDList.Add(cfgDropLibControl.ExDropLibId[i]);
                        }
                        break;
                    }
                }
            }
            //执行掉落
            List<RawItemData> finalItems = new List<RawItemData>();
            for (int i = 0; i < dropIDList.Count; i++)
            {
                for (int n = 0; n < num; n++)
                {
                    finalItems.AddRange(InnerGetDrop(player, dropIDList[i], new Counter()));
                }
            }
            return finalItems;
        }

        private List<RawItemData> InnerGetDrop(LevelPlayer player, int dropID, Counter counter)
        {
            if (counter.Value > 100)
            {
                LogicLog.LogError($"Drop Error : Recursion exists. dropID = {dropID}");
                return new List<RawItemData>();
            }

            List<RawItemData> finalItems = new List<RawItemData>();
            CfgLevelDropLib cfgDropData = TableCenter.levelDropLib.Get(dropID);
            //先计算按概率掉落
            if (cfgDropData.Weights.Count > 0 && cfgDropData.Rates.Count == 0) //按权重计算
            {
                List<int> weights = new List<int>(cfgDropData.Weights);
                // 按权重随机
                int weightSum = 0;
                foreach (int weight in weights)
                {
                    weightSum += weight;
                }
                for (int cnt = 0; cnt < cfgDropData.LoopCount; cnt++)
                {
                    if (weightSum == 0)
                    {
                        break;
                    }
                    int cursor = player.level.random.randomInt(weightSum) + 1;
                    for (int ix = 0; ix < weights.Count; ix++)
                    {
                        int weight = weights[ix];
                        if (cursor <= weight)
                        {
                            int id = cfgDropData.RandomIds[ix];
                            int num = cfgDropData.RandomCount[ix];
                            int type = cfgDropData.RandomType[ix];
                            if (id != 0)
                            {
                                if (type == 1)
                                {
                                    // 递归掉落包
                                    counter.Add();
                                    for (int j = 0; j < num; j++)
                                    {
                                        finalItems.AddRange(InnerGetDrop(player, id, counter));
                                    }
                                }
                                else if (type == 2)
                                {
                                    if (num > 0)
                                    {
                                        //CfgItem cfgItemData = TableCenter.item.Get(id);
                                        ////判断全局最大掉落数量
                                        //if (cfgItemData.DropMaxNum > 0)
                                        //{
                                        //    int oldNum = 0;
                                        //    player.ItemDropGetCnts.TryGetValue(id, out oldNum);
                                        //    if (oldNum >= cfgItemData.DropMaxNum)
                                        //    {
                                        //        //超过全局最大掉落
                                        //        weightSum -= weight;// 原始库移除此项，对应总权重需要相应减去此项的权重
                                        //        weights[ix] = 0;// 通过把权重设置为0的方式，让原始库移除此项
                                        //        if (weightSum <= 0)
                                        //        {
                                        //            //不再掉落
                                        //            break;
                                        //        }
                                        //        else
                                        //        {
                                        //            //重新循环
                                        //            ix = -1;
                                        //            cursor = player.Level.random.randomInt(weightSum) + 1;
                                        //            continue;
                                        //        }
                                        //    }
                                        //    player.ItemDropGetCnts.Remove(id);
                                        //    player.ItemDropGetCnts.Add(id, oldNum + num);
                                        //}
                                        finalItems.Add(new RawItemData(id, num));
                                    }
                                }
                            }
                            if (!cfgDropData.Repeat) //不允许重复
                            {
                                weightSum -= weight; // 原始库移除此项，对应总权重需要相应减去此项的权重
                                weights[ix] = 0; // 通过把权重设置为0的方式，让原始库移除此项
                            }
                            break;
                        }
                        else
                        {
                            cursor -= weight;
                        }
                    }
                }
            }
            else //按概率
            {
                List<float> rates = new List<float>(cfgDropData.Rates);
                for (int cnt = 0; cnt < cfgDropData.LoopCount; cnt++)
                {
                    for (int ix = 0; ix < cfgDropData.RandomIds.Count; ix++)
                    {
                        float ratio = rates[ix];
                        if (player.level.random.randomFloat() < ratio)
                        {
                            int id = cfgDropData.RandomIds[ix];
                            int num = cfgDropData.RandomCount[ix];
                            int type = cfgDropData.RandomType[ix];

                            if (id != 0)
                            {
                                if (type == 1)
                                {
                                    counter.Add();
                                    for (int k = 0; k < num; k++)
                                    {
                                        finalItems.AddRange(InnerGetDrop(player, id, counter));
                                    }
                                }
                                else if (type == 2)
                                {
                                    if (num > 0)
                                    {
                                        //CfgItem itemData = TableCenter.item.Get(id);
                                        ////判断全局最大掉落数量
                                        //if (itemData.DropMaxNum > 0)
                                        //{
                                        //    int oldNum = 0;
                                        //    player.ItemDropGetCnts.TryGetValue(id, out oldNum);
                                        //    if (oldNum >= itemData.DropMaxNum)
                                        //    {
                                        //        //超过全局最大掉落
                                        //        rates[ix] = 0;
                                        //        continue;
                                        //    }
                                        //    player.ItemDropGetCnts.Remove(id);
                                        //    player.ItemDropGetCnts.Add(id, oldNum + num);
                                        //}
                                        finalItems.Add(new RawItemData(id, num));
                                    }
                                }
                            }
                            if (!cfgDropData.Repeat) //不允许重复
                            {
                                rates[ix] = 0;
                            }
                        }
                    }
                }
            }
            //固定掉落
            for (int i = 0; i < cfgDropData.GiftItemIds.Count; i++)
            {
                if (cfgDropData.GiftItemIds[i] > 0)
                {
                    finalItems.Add(new RawItemData(cfgDropData.GiftItemIds[i], cfgDropData.GiftItemCount[i]));
                }
            }
            return finalItems;
        }

        /// <summary>
        /// 获得对应的控制表配置
        /// </summary>
        /// <param name="dropID"></param>
        /// <returns></returns>
        private CfgLevelDropLibControl GetDropLibControl(int dropID)
        {
            if (TableCenter.levelDropLibControl.dropLibIdMap.TryGetValue(dropID, out int id))
            {
                return TableCenter.levelDropLibControl.Get(id);
            }
            return null;
        }
    }


    class Counter
    {
        public int Value { get; private set; }

        public Counter()
        {
            Value = 0;
        }

        public void Add()
        {
            Value++;
        }
    }
}